| 1 | 5 |  | import express, { Express, Request, Router } from 'express'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 | 5 |  | import { pinoHttp, startTime } from 'pino-http'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | import { ServerResponse, IncomingMessage } from 'http'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 | 5 |  | import EventEmitter from 'events'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | import { ExpressBeansOptions, ExpressRouterBean } from '@/ExpressBeansTypes'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 | 5 |  | import { logger } from '@/core'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 | 5 |  | import { Executor } from '@/core/Executor'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | type ExpressBeanEventMap = { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |   error: [Error]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |   initialized: []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 | 5 |  | export default class ExpressBeans extends EventEmitter<ExpressBeanEventMap> { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 | 18 |  |   private readonly app: Express; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  |  | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 17 | 18 |  |   private readonly router: Router; | 
            
                                                                        
                            
            
                                    
            
            
                | 18 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 19 |  |  |   /** | 
            
                                                                        
                            
            
                                    
            
            
                | 20 |  |  |    * Creates a new ExpressBeans application | 
            
                                                                        
                            
            
                                    
            
            
                | 21 |  |  |    * @param options {ExpressBeansOptions} | 
            
                                                                        
                            
            
                                    
            
            
                | 22 |  |  |    */ | 
            
                                                                        
                            
            
                                    
            
            
                | 23 |  |  |   static async createApp(options?: Partial<ExpressBeansOptions>): Promise<ExpressBeans> { | 
            
                                                                        
                            
            
                                    
            
            
                | 24 | 5 |  |     const app = new ExpressBeans({ ...options }); | 
            
                                                                        
                            
            
                                    
            
            
                | 25 | 5 |  |     return app; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |   } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |   /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |    * Constructor of ExpressBeans application | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |    * @constructor | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |    * @param options {ExpressBeansOptions} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |    */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |   constructor(options?: Partial<ExpressBeansOptions>) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 | 18 |  |     super(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 | 18 |  |     this.router = express.Router(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 | 18 |  |     this.app = express(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 | 18 |  |     this.app.disable('x-powered-by'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 | 18 |  |     this.app.use(options?.baseURL ?? '/', this.router); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 | 18 |  |     if (options?.logRequests === undefined || options.logRequests) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 | 16 |  |       this.router.use(pinoHttp( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |         { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |           logger, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |           customSuccessMessage: this.serializeRequest.bind(this), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |           customErrorMessage: this.serializeRequest.bind(this), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |         }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |       )); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 | 18 |  |     Executor.setExecution('init', async () => this.initialize(options ?? {})); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 | 18 |  |     Executor.eventEmitter.on('error', () => { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 | 5 |  |       process.exit(1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |     }); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 | 18 |  |     Executor.startLifecycle(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |   } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |   private serializeRequest(req: IncomingMessage, res: ServerResponse) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 | 11 |  |     const request: Request = req as Request; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 | 11 |  |     const remoteAddress = request.headers['x-forwarded-for'] ?? request.socket.remoteAddress; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 | 11 |  |     const { method, originalUrl, httpVersion } = request; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 | 11 |  |     const responseTime = Date.now() - res[startTime]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 | 11 |  |     const optionals = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |       res.statusCode, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |       res.getHeader('content-length'), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |       res.getHeader('content-type'), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |       request.headers.referer, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |       request.headers['user-agent'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |     ] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 | 55 |  |       .filter((i) => !!i) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |       .join(' '); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 | 11 |  |     return `${remoteAddress} - "${method} ${originalUrl} HTTP/${httpVersion}" ${optionals} - ${responseTime}ms`; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |   } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |   /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |    * Initializes the application and checks | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |    * if all beans are valid | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |    * @param listen {boolean} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |    * @param port {number} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |    * @param beans {Object[]} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |    * @param onInitialized {Function} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |    * @private | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |    */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 | 15 |  |   private async initialize({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |     listen = true, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |     port = 8080, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |     routerBeans = [], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |   }: Partial<ExpressBeansOptions>) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 | 15 |  |     return Promise.resolve(routerBeans as Array<ExpressRouterBean>) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |       .then(this.checkRouterBeans.bind(this)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |       .then(this.registerRouters.bind(this)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |       .then(() => { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 | 13 |  |         if (listen) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 | 5 |  |           return new Promise<void>( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |             (resolve, reject) => { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 | 5 |  |               this.listen(port, (err) => (err ? reject(err) : resolve())); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |             }, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 | 3 |  |           ).catch((err) => Promise.reject(err)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 | 8 |  |         return Promise.resolve(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |       }); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |   } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |   /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |    * Starts the server and emits the initialized event | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |    * @param {number} port | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |    */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |   listen(port: number, callback?: (error?: Error) => void) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 | 12 |  |     return this.app.listen(port, (error) => { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 | 12 |  |       callback?.(error); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 | 12 |  |       if (error) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 | 3 |  |         this.emit('error', error); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |         return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |       } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 | 9 |  |       logger.info(`Server listening on port ${port}`); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 | 9 |  |       this.emit('initialized'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |     }); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |   } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |   /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |    * Registers all routers | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |    * @param routers {Array<ExpressRouterBean>} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |    * @private | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |    */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |   private async registerRouters(routers: Array<ExpressRouterBean>) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 | 14 |  |     return new Promise((resolve, reject) => { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 | 14 |  |       Array.from(routers) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 | 13 |  |         .map((bean) => bean._instance) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |         .forEach((instance) => { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 | 13 |  |           try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |             const { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |               path, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |               router, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 | 13 |  |             } = instance._routerConfig; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 | 13 |  |             logger.debug(`Registering router ${instance._className}`); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 | 13 |  |             this.router.use(path, router); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |           } catch (e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 | 1 |  |             logger.error(e); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 | 1 |  |             reject(new Error(`Router ${instance._className} not initialized correctly`, { cause: e })); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |           } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |         }); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 | 14 |  |       resolve(true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |     }); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |   } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |   /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |    * Checks if all beans are valid | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |    * @param routerBeans {Array<ExpressRouterBean>} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |    * @returns {Array<ExpressRouterBean>} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |    * @throws {Error} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |    * @private | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |    */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |   private async checkRouterBeans(routerBeans: Array<ExpressRouterBean>): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |   Promise<ExpressRouterBean[]> { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 | 15 |  |     const invalidBeans = routerBeans | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 | 16 |  |       .filter(((bean) => !bean._beanUUID)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 | 1 |  |       .map((object: any) => object.prototype.constructor.name); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 | 15 |  |     if (invalidBeans.length > 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 | 1 |  |       return Promise.reject(new Error(`Trying to use something that is not an ExpressBean: ${invalidBeans.join(', ')}`)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 | 14 |  |     return routerBeans; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |   } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |   /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |    * Gets Express application | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  |    * @returns {Express} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  |    */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  |   getApp() { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 | 2 |  |     return this.app; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  |   } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  |   /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  |    * Exposes use function of Express application | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  |    * @param handlers | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  |    */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  |   use(...handlers: any) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 | 1 |  |     this.app.use(...handlers); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 |  |  |   } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 176 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 177 |  |  |  |